package com.example.designpattern.behavioral.strategy;

import com.example.designpattern.behavioral.strategy.strategy.BubbleSort;
import org.junit.Test;

import java.util.Arrays;

public class Client {
    /**
     * 本例采用的是由外部客户端来显式指定某种策略，也可以由环境类根据客户端的某种需求自行判断选择何种策略（用户自己知道具体的策略）
     */
    @Test
    public void test() {
        int[] arr = new int[]{6, 1, 2, 3, 5, 4};
        Sort sort = new Sort(new BubbleSort());
        // 这里可以选择不同的策略完成排序
        // sort.setSort(new InsertSort());
        // sort.setSort(new SelectionSort());
        sort.sort(arr);
        // 输出 [1, 2, 3, 4, 5, 6]
        System.out.println(Arrays.toString(arr));
    }

    // 这就是基本的策略模式，通过策略模式我们可以为同一个需求选择不同的算法，以应付不同的场景。比如我们知道冒泡排序和插入排序是稳定的，而选择排序是不稳定的，当我们需要保证排序的稳定性就可以采用冒泡排序和插入排序，不需要保证排序的稳定性时可以采用选择排序。
    //
    //策略模式还可以应用在图片缓存中，当我们开发一个图片缓存框架时，可以通过提供不同的策略类，让用户根据需要选择缓存解码后的图片、缓存未经解码的数据或者不缓存任何内容。在一些开源的图片加载框架中，就采用了这种设计。
    //
    //策略模式扩展性和灵活性都相当不错。当有新的策略时，只需要增加一个策略类；要修改某个策略时，只需要更改具体的策略类，其他地方的代码都无需做任何调整。
    //
    //但现在这样的策略模式还有一个弊端，如本系列第一篇文章中的工厂模式所言：每 new 一个对象，相当于调用者多知道了一个类，增加了类与类之间的联系，不利于程序的松耦合。
    //
    //所以使用策略模式时，更好的做法是与工厂模式结合，将不同的策略对象封装到工厂类中，用户只需要传递不同的策略类型，然后从工厂中拿到对应的策略对象即可。接下来我们就来一起实现这种工厂模式与策略模式结合的混合模式。
}
